local storm = require 'jass.storm'
local japi = require 'jass.japi'



local panel = nil
local num = 15
local w = 500
local h = 35
local dis = 3
local len = 26

--使用热键
local use_hotkey = true

local function get_sort_list(list)
    local normal = {}
    local static = {}
    for k,v in ipairs(list) do
        if v.static then
            table.insert(static, v)
        else
            table.insert(normal, v)
        end
    end
    if #normal + #static >= 15 then
        table.remove(normal,1)
    end
    local list = {}
    for k,v in ipairs(normal) do
        table.insert(static,v)
    end
    return static
end


class.cheat_object = extends(class.panel)
{
    new = function (parent, x, y, id)
        local panel = class.cheat_object:builder
        {
            parent = parent,
            x = x,
            y = y,
            w = w,
            h = h,

            normal_image = '',

            button_background = {
                type = 'panel',
                fdf = 'tooltip_backdrop2',

                w = 128,

                button = {
                    type = 'button',
                    hide_has_event = true,
                    _act_str = true,
                    _id = id,
                },

                text = {
                    type = 'text',
                    text = '使用',
                    align = 5,
                    font_size = 12,
                }
            },

            static = {
                type = 'button',
                x = 136,
                w = h,
                _id = id,

                normal_image = [[UI\Widgets\EscMenu\Human\checkbox-background.blp]],
                yes = {
                    show_flag = false,
                    type = 'panel',
                    normal_image = [[UI\Widgets\EscMenu\Human\checkbox-check.blp]],
                },
                _static = true,
            },

            edit_background = {
                type = 'panel',
                fdf = 'tooltip_backdrop2',
                x = 136+h,
                w = w - 136-h,

                edit = {
                    type = 'text',
                    text = '',
                    x = 10,
                }
            }
        }

        return panel
    end,

    on_button_mouse_enter = function (self, button)
        button:tooltip('喊话工具', '鼠标点击|n右边可以编辑指令。', 'top')
    end,

    on_button_clicked = function (self, button)
        local id = button._id
        local info = self._cheat_info

        if not info then return end

        if button._act_str then
            ac.sync('喊话工具',info.str)
        elseif button._static then
            info.static = not info.static
            
            local sort = get_sort_list(panel:get_list())
            panel:set_list(sort)
            panel:save_cheat()
        end
    end,

    on_button_key_down = function (self, button)
        --alt 是按下状态的
        if japi.GetKeyState(0x12) then 
            local id = button._id
            local data = self._cheat_info
    
            if not data then return end
            
            ac.sync('喊话工具',data.str)
        end
    end,
}

--将lua表编码成字符串
local encode = function (tbl)
    local type = type
    local pairs = pairs
    local format = string.format
    local find = string.find
    local tostring = tostring
    local tonumber = tonumber
    local mark = {}
    local buf = {}
    local count = 0
    local function dump(v)
        local tp = type(v)
        if mark[v] then
            error('表结构中有循环引用')
        end
        mark[v] = true
        buf[#buf+1] = '{'
        local ator = pairs 
        if #v > 0 then 
            ator = ipairs
        end
        for k, v in ator(v) do
            count = count + 1
            if count > 1000 then
                error('表太大了')
            end
            local tp = type(k)
            if tp == 'number' then
                if ator == pairs then 
                    buf[#buf+1] = format('[%s]=', k)
                end 
            elseif tp == 'string' then
                if find(k, '[^%w_]') then
                    buf[#buf+1] = format('[%q]=', k)
                else
                    buf[#buf+1] = k..'='
                end
            else
                error('不支持的键类型：'..tp)
            end
            local tp = type(v)
            if tp == 'table' then
                dump(v)
            elseif tp == 'number' then
                buf[#buf+1] = format('%q', v)
            elseif tp == 'string' then
                buf[#buf+1] = format('%q', v)
            elseif tp == 'boolean' then
                buf[#buf+1] = format('%s', v)
            else
                log.error('不支持的值类型：'..tp)
            end
            buf[#buf+1] = ','
        end
        if buf[#buf] == ',' then 
            table.remove(buf, #buf)
        end 
        buf[#buf+1] = '}'
    end
    dump(tbl)
    return table.concat(buf)
end

--将字符串 加载为lua表
local decode = function (buf)
    if buf:find('%(') or buf:find("%)") then 
        return 
    end 
    
    local f, err = load('return '..buf)
    if not f then
        print(err)
        return nil
    end
    local suc, res = pcall(f)
    if not suc then
        print(res)
        return nil
    end
    return res
end
class.cheat_panel = extends(class.panel)
{
    create = function ()

        local panel = class.cheat_panel:builder
        {
            fdf = 'tooltip_backdrop2',
            x = 1920 - w-10,
            y = 100,
            w = w+dis*2,
            h = (h+dis)*num+dis,
            --show_flag = false,
        }


        local list = {}

        for i = 1, num do 
            local y = (dis+h) * (num - i) + dis
            local child = panel:add(class.cheat_object, dis, y )
            local button = child.button_background.button
            local text = child.button_background.text
            if use_hotkey then
                button.keys = {i}
                text:set_text('Alt + ' .. tostring(i) )
            else
                text:set_text('[' .. tostring(i) .. ']')
            end
            list[i] = child
        end 
        panel.list = list

        --panel:set_control_size(panel.w, y)
        return panel
    end,

    set_list = function (self, list)
        for index, info in ipairs(list) do 
            local child = self.list[index]
            if child then 
                child.edit_background.edit:set_text(info.str)
                child._cheat_info = info
                if info.static then
                    child.static.yes:show()
                else
                    child.static.yes:hide()
                end
            else
                child.static.yes:hide()
            end     
        end 
    end,

    get_list = function (self)
        local s = {}

        for index, child in ipairs(self.list) do 
            s[index] = child._cheat_info
        end 
        return s
    end,

    load_cheat = function (self)
        local str = storm.load("ui\\cheat2.0.txt")
        if str == nil then 
            return 
        end 
        local list = decode(str)
        self:set_list(list)
    end,

    save_cheat = function (self)
        storm.save("ui\\cheat2.0.txt", encode(self:get_list()))
    end,


    on_edit_text_changed = function (self, edit, new_str, old_str)
        self:save_cheat()
    end,
}

panel = class.cheat_panel.create()
panel:load_cheat()
panel:hide()

local button = class.button:builder
{
    x = 1920-64-10,
    y = panel.y + panel.h + 10,
    w = 64,
    h = 64,
    ani_flag = true,
    normal_image = [[image\bantouming.blp]],
}

function button:on_button_clicked()
    if panel:is_show() then 
        panel:hide()
        self:set_normal_image('ui\\图鉴\\4.tga')
    else 
        panel:show()
        self:set_normal_image('ui\\图鉴\\3.tga')
    end
end


local on_button_mouse_enter = button.on_button_mouse_enter
function button:on_button_mouse_enter()
    if on_button_mouse_enter then 
        on_button_mouse_enter(self)
    end
    self:tooltip('喊话工具', '点击显示或隐藏喊话工具|n 正式版里不会出现', 'left', 300)
end 



ac.game:event '玩家-聊天' (function(trg, player, str, is_local)
    if is_local then 
        return 
    end 

    if player:is_self() ~= true then 
        return 
    end 


    if str:sub(1, 1) == '-' then 
 
        local list = panel:get_list()
        for index, s in ipairs(list) do 
            if s.str == str then 
                return 
            end
        end 
        table.insert(list, {
            static = false,
            str = str,
        })
        --if #list > #panel.list then 
        --    table.remove(list, 1)
        --end 

        --设置保存
        local sort = get_sort_list(list)

        panel:set_list( sort )
        panel:save_cheat()
    end 
end)

ac.sync:event '喊话工具'(function(_,player,str)
    japi.EXDisplayChat(player.handle, 1, str)
    player:notify('玩家-聊天', player, str, true)
end)
